package com.qsl.task.config;

import com.google.common.collect.Lists;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.discovery.shared.Application;
import com.netflix.eureka.EurekaServerContextHolder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
import org.springframework.cloud.loadbalancer.core.RoundRobinLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import reactor.core.publisher.Flux;

import java.util.List;

/**
 * 负载均衡策略是轮询，支持自定义策略
 */
@Configuration
@LoadBalancerClient(name = "loadBalancer", configuration = RoundRobinLoadBalancer.class)
public class RestTemplateConfig {

    @Value("${executor.application.name:TASK-EXECUTOR}")
    private String executorApplicationName;

    /**
     * 连接池获取连接的超时时长，单位毫秒；默认 10秒
     */
    @Value("${rest.connection.connection-request-timeout:10000}")
    private int connectionRequestTimeout;
    /**
     * 与外部系统建立连接的超时时长，单位毫秒；默认10秒
     */
    @Value("${rest.connection.connect-timeout:10000}")
    private int connectTimeout;
    /**
     * 等待外部系统响应的超时时长，单位毫秒；默认60秒
     */
    @Value("${rest.connection.read-timeout:60000}")
    private int readTimeout;

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        //配置HTTP超时时间
        HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
        httpRequestFactory.setConnectionRequestTimeout(connectionRequestTimeout);
        httpRequestFactory.setConnectTimeout(connectTimeout);
        httpRequestFactory.setReadTimeout(readTimeout);
        return new RestTemplate(httpRequestFactory);
    }

    /**
     * 任务执行器服务实例列表供应者
         多个服务，则需要配置多个
     * @return 任务执行器服务实例列表
     */
    @Bean
    @Primary
    ServiceInstanceListSupplier serviceInstanceListSupplier() {
        return new ServiceInstanceListSupplier() {
            @Override
            public String getServiceId() {
                return executorApplicationName;
            }

            @Override
            public Flux<List<ServiceInstance>> get() {
                EurekaServerContextHolder instanceHolder = EurekaServerContextHolder.getInstance();
                // 获取执行器服务
                Application application = instanceHolder.getServerContext()
                        .getRegistry().getApplication(executorApplicationName);
                List<ServiceInstance> serviceInstances = Lists.newArrayList();
                for (InstanceInfo instanceInfo : application.getInstances()) {
                    DefaultServiceInstance defaultServiceInstance = new DefaultServiceInstance(
                            instanceInfo.getInstanceId(), instanceInfo.getAppName(),
                            instanceInfo.getHostName(), instanceInfo.getPort(), false);
                    serviceInstances.add(defaultServiceInstance);
                }
                return Flux.just(serviceInstances);
            }
        };
    }
}